package configs

import (
	"bufio"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
)

// 位置的结构体
type Position struct {
	Idx   int    // 索引位置
	Ln    int    // 行号
	Col   int    // 列号
	Fn    string // 文件
	FText string // 文件
}

// 错误
type Error struct {
	PosStart  *Position // 错误的开始位置
	PosEnd    *Position // 错误的结束位置
	ErrorName string    // 错误名称
	Details   string    // 错误详情
}
type RTResult struct {
	Value              interface{} // 值
	Error_             *Error      // 错误
	FuncReturnValue    interface{} // 函数的返回值
	LoopShouldContinue bool        // 循环应该 continue
	LoopShouldBreak    bool        // 循环应该打断 break
}

// 转化为错误字符串
func (e *Error) ToString() string {
	result_ := "错误名称：" + e.ErrorName + "\n"
	result_ += "错误详情：" + e.Details + "\n"
	result_ += "错误文件：" + e.PosStart.Fn + "，行数：" + strconv.Itoa(e.PosEnd.Ln+1) + "\n"
	return result_
}

// 配置的全局变量，存储了所有的配置文件内容
var Configs = make(map[string]interface{})

// 解析配置文件
func ParseConfig(name interface{}) *RTResult {

	result := &RTResult{
		Value:              nil,
		Error_:             nil,
		FuncReturnValue:    nil,
		LoopShouldContinue: false,
		LoopShouldBreak:    false,
	}
	if name == nil || name == "" {
		name = `config.ini`
	}
	_, file_, _, _ := runtime.Caller(1)
	path := filepath.Dir(file_)
	path = "./" + name.(string)
	file, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	rd := bufio.NewReader(file)
	var lineNum = 0

	for {
		lineNum++
		line, err := rd.ReadString('\n')
		line = strings.Trim(line, "\n")
		line = strings.Trim(line, "\t")
		line = strings.Trim(line, "\r")
		line = strings.Trim(line, " ")
		if err != nil || io.EOF == err {
			ReadLine(path, line, result, lineNum)
			return result
		} else {
			if (len(line) > 0 && (string(line[0]) == "#" || string(line[0]) == "ï")) || line == "" { // 表示是注释
				continue
			} else { // 是内容
				ReadLine(path, line, result, lineNum)
			}
		}
	}
	return result
}

func ReadLine(path string, line string, result *RTResult, lineNum int) {
	t := strings.Split(line, "=")
	pos := &Position{
		Idx:   0,
		Ln:    lineNum,
		Col:   0,
		Fn:    path,
		FText: line,
	}
	if len(t) != 2 {
		err_ := &Error{
			PosStart:  pos,
			PosEnd:    pos,
			ErrorName: "配置文件错误",
			Details:   "在第 " + strconv.Itoa(lineNum) + " 行的配置语法错误，应该是 a=1 的格式",
		}
		result.Error_ = err_
	}
	k := strings.Trim(t[0], " ")
	v := strings.Trim(t[1], " ")
	res, err := strconv.Atoi(v)
	if err == nil {
		Configs[k] = res
	} else {
		Configs[k] = v
	}
	result.Value = Configs
}

// 得到配置文件
func GetConfig(name string) interface{} {
	return Configs[name]
}
